/*                         
 * JSmbScannerView.java
 */
package jsmbscanner;
/*
 * GNU GENERAL PUBLIC LICENSE
 * Version 3, 29 June 2007
 *
 * Copyright (C) 2009, vlad
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.awt.Toolkit;
import java.net.UnknownHostException;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.Task;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

/**
 * The application's main frame.
 */
public class JSmbScannerView extends FrameView {

    static boolean errorOutput = false;

    public JSmbScannerView(SingleFrameApplication app) {
        super(app);

        initComponents();

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });


    }

    //
    @Action
    public Task startScan() {
        return new RefreshTask(getApplication());
    }

    public void fillInfoPanel() {
        // Transfer information from Option dialog
        textFieldNetwork.setText(SetSetup.getNetworkAddress());
        textFieldBroadcast.setText(SetSetup.getNetworkBroadcast());
        textFieldClass.setText(SetSetup.getNetworkClass());
        textFieldHostMax.setText(SetSetup.getStopIPtext());
        textFieldHostMin.setText(SetSetup.getStartIPtext());
        textFieldHosts.setText(SetSetup.getHostCount());
        textFieldMask.setText(SetSetup.getMaskCIDR());
        panelInfo.revalidate();
        panelInfo.repaint();
    }

    public void controlStartButtons(boolean status) {
        buttonStart.setEnabled(status);
        startMenuItem.setEnabled(status);
    }

    // That task do the main work
    private class RefreshTask extends Task {

        RefreshTask(org.jdesktop.application.Application app) {
            super(app);
        }

        //@SuppressWarnings("unchecked")
        @Override
        protected Void doInBackground() throws TimeoutException {
            controlStartButtons(false);
            long stopAddress = 0L;
            long startAddress = 0L;
            try {
                if (setSetup != null) {
                    // Let's go!!
                    startAddress = SetSetup.getStartIP();
                    stopAddress = SetSetup.getStopIP();
                    fillInfoPanel();
                } else {
                    // You don't set range of work
                    Toolkit.getDefaultToolkit().beep();
                    setMessage("Warning: You didn't set range of IP ! I use default configuration.");
                    Thread.sleep(2000L); // Stop
                    try {
                        // Stop
                        startAddress = InetTools.AddressToNum("10.0.11.2");
                        stopAddress = InetTools.AddressToNum("10.0.11.20");
                        textFieldHostMax.setText("10.0.11.20");
                        textFieldHostMin.setText("10.0.11.2");
                    } catch (UnknownHostException ex) {
                        System.out.println("Transfering IP address to number has been caught exception. Problem is..." + ex);
                        if (errorOutput) {
                            Logger.getLogger(JSmbScannerView.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                }

                int startBar = (int) startAddress;
                int stopBar = (int) stopAddress;
                setProgress(startBar, startBar, stopBar);
                DefaultTableModel tableModel = (DefaultTableModel) mainTable.getModel();
                // Get timeout from form
                int timeOut = Integer.decode(formatedTimeout.getText()); // Ping timeout
                System.out.println("Timeout is " + timeOut);

                int host_counter = 0;
                String full_ip = "-";
                ExecutorService pool = Executors.newCachedThreadPool();
                // ExecutorService pool = Executors.newFixedThreadPool(10);
                Set<Future<String>> set = new HashSet<Future<String>>();


                System.out.println("StartIP is " + startAddress);
                System.out.println("StopIP is " + stopAddress);

                setMessage("Start working threads...");
                setProgress(0, 0, 100);
                // Setting up the task
                for (long i = startAddress; i <= stopAddress; i++) {
                    host_counter++;
                    try {
                        full_ip = InetTools.NumToAddress(i);
                    } catch (UnknownHostException ex) {
                        Logger.getLogger(JSmbScannerView.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    Callable<String> callable = new NetworkWorker("Num " + i, full_ip, timeOut);
                    Future<String> future = pool.submit(callable);
                    set.add(future);
                    //pool.execute(new NetworkWorker("Num " + i, full_ip,
                    //timeOut, exgr));
                    //pool.submit(new NetworkWorker("Num " + i, full_ip, timeOut, exgr));
                }
                System.out.println("Parent process. Host counter=" + host_counter);

                setMessage("Getting results...");
                setProgress(50, 0, 100);
                // Getting results
                host_counter = 0;
                String dns_name = "-";     //FQDN
                String nbt_name = "-";
                String work_group = "-";
                String mac = "*";
                String[] hosts = new String[5];
                String threadAnswer = null;
                int row_count = tableModel.getRowCount() - 1; //Count row
                // Clear table
                for (int i = 0; i <= row_count; i++) {
                    tableModel.setValueAt("", i, 0);
                    tableModel.setValueAt("", i, 1);
                    tableModel.setValueAt("", i, 2);
                    tableModel.setValueAt("", i, 3);
                    tableModel.setValueAt("", i, 4);
                }
                tableModel.fireTableDataChanged();
                int table_lines = 0;
                int all_hosts = set.size();
                for (Future<String> future : set) {
                    // Processing information
                    try {
                        threadAnswer = future.get(timeOut * 3, TimeUnit.MILLISECONDS);
                        //System.out.println("Results =" + threadAnswer);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(JSmbScannerView.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (ExecutionException ex) {
                        Logger.getLogger(JSmbScannerView.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (TimeoutException ex) {
                        System.out.println("threadAnswer couldn't get result");
                        Logger.getLogger(JSmbScannerView.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    if (!threadAnswer.equals("false")) {
                        System.out.println("-> Main received: " + threadAnswer + " done");
                        int index_0, index_1, index_2, index_3, index_4,
                                index_5;
                        index_0 = threadAnswer.indexOf("/");
                        index_1 = threadAnswer.indexOf("/", index_0 + 1);
                        index_2 = threadAnswer.indexOf("/", index_1 + 1);
                        index_3 = threadAnswer.indexOf("/", index_2 + 1);
                        index_4 = threadAnswer.indexOf("/", index_3 + 1);
                        index_5 = threadAnswer.lastIndexOf("/");
                        nbt_name = threadAnswer.substring(index_0 + 1, index_1);
                        work_group = threadAnswer.substring(index_1 + 1, index_2);
                        dns_name = threadAnswer.substring(index_2 + 1, index_3);
                        mac = threadAnswer.substring(index_3 + 1, index_4);
                        full_ip = threadAnswer.substring(index_5 + 1);


                        System.out.println(nbt_name + "   " + work_group + "  " + dns_name + "   " + mac + "   " + full_ip);
                        // Fill our mainTable
                        if (row_count > table_lines) {
                            // System.out.println("SET Values >");
                            tableModel.setValueAt(full_ip, table_lines, 0);
                            tableModel.setValueAt(nbt_name, table_lines, 1);
                            tableModel.setValueAt(work_group, table_lines, 2);
                            tableModel.setValueAt(dns_name, table_lines, 3);
                            tableModel.setValueAt(mac, table_lines, 4);
                            tableModel.fireTableRowsUpdated(table_lines, row_count);
                        } else {
                            // We need to add some Rows
                            // System.out.println("INSERT data >>");
                            hosts[0] = full_ip;
                            hosts[1] = nbt_name;
                            hosts[2] = work_group;
                            hosts[3] = dns_name;
                            hosts[4] = mac;
                            tableModel.insertRow(row_count, hosts);
                            tableModel.fireTableRowsInserted(row_count - 1, row_count);
                        }
                        table_lines++;

                    } else {
                        System.out.println("skip!");
                    }

                    host_counter++;
                }
                System.out.println("Parent process. Host counter=" + host_counter);
                setProgress(100, 0, 100);

            } catch (InterruptedException ex) {
                System.out.println("Exception(main block) is..." + ex);
                if (errorOutput) {
                    Logger.getLogger(JSmbScannerView.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            return null;
        }

        @Override
        protected void finished() {
            setMessage("Done.");
            controlStartButtons(true);
        }
    }

    // Show dialog About
    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = JSmbScannerApp.getApplication().getMainFrame();
            aboutBox = new JSmbScannerAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        JSmbScannerApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        toolbarMain = new javax.swing.JToolBar();
        buttonStart = new javax.swing.JButton();
        buttonOptions = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        buttonExit = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        lanelTimeout = new javax.swing.JLabel();
        formatedTimeout = new javax.swing.JFormattedTextField();
        jLabel2 = new javax.swing.JLabel();
        panelInfo = new javax.swing.JPanel();
        labelNetwork = new javax.swing.JLabel();
        textFieldNetwork = new javax.swing.JTextField();
        labelHostMin = new javax.swing.JLabel();
        textFieldHostMin = new javax.swing.JTextField();
        labelHostMax = new javax.swing.JLabel();
        textFieldHostMax = new javax.swing.JTextField();
        textFieldBroadcast = new javax.swing.JTextField();
        labelBroadcast = new javax.swing.JLabel();
        textFieldHosts = new javax.swing.JTextField();
        labelHosts = new javax.swing.JLabel();
        labelClass = new javax.swing.JLabel();
        textFieldClass = new javax.swing.JTextField();
        labelMask = new javax.swing.JLabel();
        textFieldMask = new javax.swing.JTextField();
        scrollpanelMain = new javax.swing.JScrollPane();
        mainTable = new javax.swing.JTable();
        tbuttonHidePanelInfo = new javax.swing.JToggleButton();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu actionMenu = new javax.swing.JMenu();
        startMenuItem = new javax.swing.JMenuItem();
        optionMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N

        toolbarMain.setFloatable(false);
        toolbarMain.setName("toolbarMain"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jsmbscanner.JSmbScannerApp.class).getContext().getActionMap(JSmbScannerView.class, this);
        buttonStart.setAction(actionMap.get("startScan")); // NOI18N
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jsmbscanner.JSmbScannerApp.class).getContext().getResourceMap(JSmbScannerView.class);
        buttonStart.setIcon(resourceMap.getIcon("buttonStart.icon")); // NOI18N
        buttonStart.setText(resourceMap.getString("buttonStart.text")); // NOI18N
        buttonStart.setFocusable(false);
        buttonStart.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonStart.setName("buttonStart"); // NOI18N
        buttonStart.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        toolbarMain.add(buttonStart);

        buttonOptions.setAction(actionMap.get("showSetSetup")); // NOI18N
        buttonOptions.setIcon(resourceMap.getIcon("buttonOptions.icon")); // NOI18N
        buttonOptions.setText(resourceMap.getString("buttonOptions.text")); // NOI18N
        buttonOptions.setToolTipText(resourceMap.getString("buttonOptions.toolTipText")); // NOI18N
        buttonOptions.setFocusable(false);
        buttonOptions.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonOptions.setMaximumSize(new java.awt.Dimension(44, 44));
        buttonOptions.setMinimumSize(new java.awt.Dimension(44, 44));
        buttonOptions.setName("buttonOptions"); // NOI18N
        buttonOptions.setPreferredSize(new java.awt.Dimension(44, 44));
        buttonOptions.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        toolbarMain.add(buttonOptions);

        jSeparator2.setName("jSeparator2"); // NOI18N
        jSeparator2.setSeparatorSize(new java.awt.Dimension(25, 20));
        toolbarMain.add(jSeparator2);

        buttonExit.setAction(actionMap.get("quit")); // NOI18N
        buttonExit.setIcon(resourceMap.getIcon("buttonExit.icon")); // NOI18N
        buttonExit.setText(resourceMap.getString("buttonExit.text")); // NOI18N
        buttonExit.setToolTipText(resourceMap.getString("buttonExit.toolTipText")); // NOI18N
        buttonExit.setFocusable(false);
        buttonExit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonExit.setName("buttonExit"); // NOI18N
        buttonExit.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        toolbarMain.add(buttonExit);

        jSeparator1.setName("jSeparator1"); // NOI18N
        jSeparator1.setSeparatorSize(new java.awt.Dimension(150, 20));
        toolbarMain.add(jSeparator1);

        lanelTimeout.setText(resourceMap.getString("lanelTimeout.text")); // NOI18N
        lanelTimeout.setName("lanelTimeout"); // NOI18N
        toolbarMain.add(lanelTimeout);

        formatedTimeout.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        formatedTimeout.setText(resourceMap.getString("formatedTimeout.text")); // NOI18N
        formatedTimeout.setMaximumSize(new java.awt.Dimension(90, 25));
        formatedTimeout.setName("formatedTimeout"); // NOI18N
        toolbarMain.add(formatedTimeout);

        jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N
        jLabel2.setName("jLabel2"); // NOI18N
        toolbarMain.add(jLabel2);

        panelInfo.setBorder(javax.swing.BorderFactory.createTitledBorder(null, resourceMap.getString("panelInfo.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, resourceMap.getFont("panelInfo.border.titleFont"))); // NOI18N
        panelInfo.setName("panelInfo"); // NOI18N

        labelNetwork.setText(resourceMap.getString("labelNetwork.text")); // NOI18N
        labelNetwork.setName("labelNetwork"); // NOI18N

        textFieldNetwork.setEditable(false);
        textFieldNetwork.setText(resourceMap.getString("textFieldNetwork.text")); // NOI18N
        textFieldNetwork.setBorder(null);
        textFieldNetwork.setName("textFieldNetwork"); // NOI18N

        labelHostMin.setText(resourceMap.getString("labelHostMin.text")); // NOI18N
        labelHostMin.setName("labelHostMin"); // NOI18N

        textFieldHostMin.setEditable(false);
        textFieldHostMin.setText(resourceMap.getString("textFieldHostMin.text")); // NOI18N
        textFieldHostMin.setBorder(null);
        textFieldHostMin.setName("textFieldHostMin"); // NOI18N

        labelHostMax.setText(resourceMap.getString("labelHostMax.text")); // NOI18N
        labelHostMax.setName("labelHostMax"); // NOI18N

        textFieldHostMax.setEditable(false);
        textFieldHostMax.setText(resourceMap.getString("textFieldHostMax.text")); // NOI18N
        textFieldHostMax.setBorder(null);
        textFieldHostMax.setName("textFieldHostMax"); // NOI18N

        textFieldBroadcast.setEditable(false);
        textFieldBroadcast.setText(resourceMap.getString("textFieldBroadcast.text")); // NOI18N
        textFieldBroadcast.setToolTipText(resourceMap.getString("textFieldBroadcast.toolTipText")); // NOI18N
        textFieldBroadcast.setBorder(null);
        textFieldBroadcast.setName("textFieldBroadcast"); // NOI18N

        labelBroadcast.setText(resourceMap.getString("labelBroadcast.text")); // NOI18N
        labelBroadcast.setName("labelBroadcast"); // NOI18N

        textFieldHosts.setEditable(false);
        textFieldHosts.setText(resourceMap.getString("textFieldHosts.text")); // NOI18N
        textFieldHosts.setBorder(null);
        textFieldHosts.setName("textFieldHosts"); // NOI18N

        labelHosts.setText(resourceMap.getString("labelHosts.text")); // NOI18N
        labelHosts.setName("labelHosts"); // NOI18N

        labelClass.setText(resourceMap.getString("labelClass.text")); // NOI18N
        labelClass.setName("labelClass"); // NOI18N

        textFieldClass.setEditable(false);
        textFieldClass.setForeground(resourceMap.getColor("textFieldClass.foreground")); // NOI18N
        textFieldClass.setText(resourceMap.getString("textFieldClass.text")); // NOI18N
        textFieldClass.setBorder(null);
        textFieldClass.setName("textFieldClass"); // NOI18N

        labelMask.setText(resourceMap.getString("labelMask.text")); // NOI18N
        labelMask.setName("labelMask"); // NOI18N

        textFieldMask.setEditable(false);
        textFieldMask.setText(resourceMap.getString("textFieldMask.text")); // NOI18N
        textFieldMask.setBorder(null);
        textFieldMask.setName("textFieldMask"); // NOI18N

        javax.swing.GroupLayout panelInfoLayout = new javax.swing.GroupLayout(panelInfo);
        panelInfo.setLayout(panelInfoLayout);
        panelInfoLayout.setHorizontalGroup(
                panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(panelInfoLayout.createSequentialGroup().addContainerGap().addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(labelNetwork).addComponent(labelHostMin).addComponent(labelHostMax).addComponent(labelBroadcast)).addGap(35, 35, 35).addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(textFieldBroadcast, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addGroup(panelInfoLayout.createSequentialGroup().addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(textFieldHostMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(textFieldHostMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(textFieldNetwork, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(labelHosts).addComponent(labelClass).addComponent(labelMask)).addGap(18, 18, 18).addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(textFieldClass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(textFieldHosts, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(textFieldMask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))).addContainerGap()));
        panelInfoLayout.setVerticalGroup(
                panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(panelInfoLayout.createSequentialGroup().addContainerGap().addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(panelInfoLayout.createSequentialGroup().addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(labelNetwork).addComponent(textFieldNetwork, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(labelHostMin).addComponent(textFieldHostMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(labelHostMax).addComponent(textFieldHostMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(labelBroadcast).addComponent(textFieldBroadcast, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))).addGroup(panelInfoLayout.createSequentialGroup().addComponent(textFieldClass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(textFieldHosts, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(textFieldMask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addGroup(panelInfoLayout.createSequentialGroup().addComponent(labelClass).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(labelHosts).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(labelMask))).addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        scrollpanelMain.setName("scrollpanelMain"); // NOI18N

        mainTable.setAutoCreateRowSorter(true);
        mainTable.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{
                    {null, null, null, null, null},
                    {null, null, null, null, null},
                    {null, null, null, null, null}
                },
                new String[]{
                    "IP address", "NetBIOS name", "NBT group", "DNS Name", "MAC-address"
                }) {

            Class[] types = new Class[]{
                java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean[]{
                false, false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit[columnIndex];
            }
        });
        mainTable.setColumnSelectionAllowed(true);
        mainTable.setName("mainTable"); // NOI18N
        mainTable.getTableHeader().setReorderingAllowed(false);
        scrollpanelMain.setViewportView(mainTable);
        mainTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        mainTable.getColumnModel().getColumn(0).setMinWidth(80);
        mainTable.getColumnModel().getColumn(0).setPreferredWidth(85);
        mainTable.getColumnModel().getColumn(0).setMaxWidth(95);
        mainTable.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("mainTable.columnModel.title0")); // NOI18N
        mainTable.getColumnModel().getColumn(1).setMinWidth(75);
        mainTable.getColumnModel().getColumn(1).setPreferredWidth(100);
        mainTable.getColumnModel().getColumn(1).setMaxWidth(125);
        mainTable.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("mainTable.columnModel.title1")); // NOI18N
        mainTable.getColumnModel().getColumn(2).setMinWidth(60);
        mainTable.getColumnModel().getColumn(2).setPreferredWidth(80);
        mainTable.getColumnModel().getColumn(2).setMaxWidth(90);
        mainTable.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("mainTable.columnModel.title2")); // NOI18N
        mainTable.getColumnModel().getColumn(3).setHeaderValue(resourceMap.getString("mainTable.columnModel.title3")); // NOI18N
        mainTable.getColumnModel().getColumn(4).setResizable(false);
        mainTable.getColumnModel().getColumn(4).setPreferredWidth(130);
        mainTable.getColumnModel().getColumn(4).setHeaderValue(resourceMap.getString("mainTable.columnModel.title4")); // NOI18N

        tbuttonHidePanelInfo.setAction(actionMap.get("hidePanelInfo")); // NOI18N
        tbuttonHidePanelInfo.setIcon(resourceMap.getIcon("tbuttonHidePanelInfo.icon")); // NOI18N
        tbuttonHidePanelInfo.setText(resourceMap.getString("tbuttonHidePanelInfo.text")); // NOI18N
        tbuttonHidePanelInfo.setToolTipText(resourceMap.getString("tbuttonHidePanelInfo.toolTipText")); // NOI18N
        tbuttonHidePanelInfo.setName("tbuttonHidePanelInfo"); // NOI18N
        tbuttonHidePanelInfo.setSelectedIcon(resourceMap.getIcon("tbuttonHidePanelInfo.selectedIcon")); // NOI18N

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
                mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(mainPanelLayout.createSequentialGroup().addContainerGap().addComponent(panelInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addContainerGap()).addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup().addContainerGap(452, Short.MAX_VALUE).addComponent(tbuttonHidePanelInfo).addContainerGap()).addComponent(toolbarMain, javax.swing.GroupLayout.DEFAULT_SIZE, 514, Short.MAX_VALUE).addGroup(mainPanelLayout.createSequentialGroup().addContainerGap().addComponent(scrollpanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, 490, Short.MAX_VALUE).addContainerGap()));
        mainPanelLayout.setVerticalGroup(
                mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(mainPanelLayout.createSequentialGroup().addComponent(toolbarMain, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(scrollpanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, 373, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addComponent(tbuttonHidePanelInfo).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(panelInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addGap(46, 46, 46)));

        menuBar.setName("menuBar"); // NOI18N

        actionMenu.setText(resourceMap.getString("actionMenu.text")); // NOI18N
        actionMenu.setName("actionMenu"); // NOI18N

        startMenuItem.setAction(actionMap.get("startScan")); // NOI18N
        startMenuItem.setIcon(resourceMap.getIcon("startMenuItem.icon")); // NOI18N
        startMenuItem.setText(resourceMap.getString("startMenuItem.text")); // NOI18N
        startMenuItem.setName("startMenuItem"); // NOI18N
        actionMenu.add(startMenuItem);

        optionMenuItem.setAction(actionMap.get("showSetSetup")); // NOI18N
        optionMenuItem.setIcon(resourceMap.getIcon("optionMenuItem.icon")); // NOI18N
        optionMenuItem.setText(resourceMap.getString("optionMenuItem.text")); // NOI18N
        optionMenuItem.setName("optionMenuItem"); // NOI18N
        actionMenu.add(optionMenuItem);

        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setIcon(resourceMap.getIcon("exitMenuItem.icon")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        actionMenu.add(exitMenuItem);

        menuBar.add(actionMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setIcon(resourceMap.getIcon("aboutMenuItem.icon")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
                statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 514, Short.MAX_VALUE).addGroup(statusPanelLayout.createSequentialGroup().addContainerGap().addComponent(statusMessageLabel).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 330, Short.MAX_VALUE).addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(statusAnimationLabel).addContainerGap()));
        statusPanelLayout.setVerticalGroup(
                statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(statusPanelLayout.createSequentialGroup().addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(statusMessageLabel).addComponent(statusAnimationLabel).addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addGap(3, 3, 3)));

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
        setToolBar(toolbarMain);
    }// </editor-fold>//GEN-END:initComponents

    private void formComponentHidden(java.awt.event.ComponentEvent evt) {
        // Refresh info panel
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                fillInfoPanel();
            }
        });

    }

    @Action
    public void showSetSetup() {
        if (setSetup == null) {
            // Initialize Options dialog
            JFrame mainFrame = JSmbScannerApp.getApplication().getMainFrame();
            setSetup = new SetSetup(mainFrame, true);

            SwingUtilities.invokeLater(new Runnable() {
                //SwingUtilities.invokeAndWait(new Runnable() {

                public void run() {
                    setSetup.setVisible(true);
                }
            });
            setSetup.addComponentListener(new java.awt.event.ComponentAdapter() {

                @Override
                public void componentHidden(java.awt.event.ComponentEvent evt) {
                    formComponentHidden(evt);
                }
            });

        } else {
            setSetup.setVisible(true);
        }
    }

    @Action
    public void hidePanelInfo() {
        if (!tbuttonHidePanelInfo.isSelected()) {
            panelInfo.setVisible(true);
            mainPanel.revalidate();
            mainPanel.repaint();
        } else {
            panelInfo.setVisible(false);
            mainPanel.revalidate();
            mainPanel.repaint();
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonExit;
    private javax.swing.JButton buttonOptions;
    private javax.swing.JButton buttonStart;
    private javax.swing.JFormattedTextField formatedTimeout;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JLabel labelBroadcast;
    private javax.swing.JLabel labelClass;
    private javax.swing.JLabel labelHostMax;
    private javax.swing.JLabel labelHostMin;
    private javax.swing.JLabel labelHosts;
    private javax.swing.JLabel labelMask;
    private javax.swing.JLabel labelNetwork;
    private javax.swing.JLabel lanelTimeout;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JTable mainTable;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem optionMenuItem;
    private javax.swing.JPanel panelInfo;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JScrollPane scrollpanelMain;
    private javax.swing.JMenuItem startMenuItem;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JToggleButton tbuttonHidePanelInfo;
    private javax.swing.JTextField textFieldBroadcast;
    private javax.swing.JTextField textFieldClass;
    private javax.swing.JTextField textFieldHostMax;
    private javax.swing.JTextField textFieldHostMin;
    private javax.swing.JTextField textFieldHosts;
    private javax.swing.JTextField textFieldMask;
    private javax.swing.JTextField textFieldNetwork;
    private javax.swing.JToolBar toolbarMain;              
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private JDialog aboutBox;
    private SetSetup setSetup;
    // End of variables declaration//GEN-END:variables


}
